package com.order.manager.controller.Order;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.order.manager.Model.*;
import com.order.manager.Model.other.MenuCount;
import com.order.manager.Model.other.OrderCreationRequest;
import com.order.manager.Model.other.OrderView;
import com.order.manager.Model.other.RestBean;
import com.order.manager.service.impl.*;
import com.order.manager.util.JwtUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * 订单管理控制器
 * 处理订单的创建、查询、支付、退款等全生命周期管理
 */
@RestController
@RequestMapping("/api/order")
public class OrderController {

    // 注入订单信息服务，处理订单核心业务逻辑
    // @Resource 的核心作用
    //依赖注入：无需手动创建对象，由容器（如 Spring）自动创建并注入到需要的地方
    @Resource
    OrderInfoServiceImpl orderInfoService;

    // 注入店铺信息服务，用于获取店铺相关信息
    @Resource
    ShopInfoServiceImpl shopInfoService;

    // 注入菜单信息服务，用于获取菜品相关信息
    @Resource
    MenuInfoServiceImpl menuInfoService;

    // 注入用户信息服务，用于获取用户相关信息
    @Resource
    UserInfoServiceImpl userInfoService;

    // 注入配送员信息服务，用于获取配送员相关信息
    @Resource
    SenderInfoServiceImpl senderInfoService;

    // 注入评价信息服务，用于获取评价相关信息
    @Resource
    EvaluateInfoServiceImpl evaluateInfoService;

    // 注入用户地址服务，用于获取用户地址相关信息
    @Resource
    UserAddressServiceImpl userAddressService;

    // 注入订单配送信息服务，用于获取订单配送相关信息
    @Resource
    OrderSendInfoServiceImpl orderSendInfoService;

    // 注入JWT工具类，用于解析用户身份信息
    @Resource
    JwtUtil jwtUtil;

    // 注入订单菜单关联服务，用于处理订单与菜品的关联关系
    @Resource
    OrderMenuInfoServiceImpl orderMenuInfoService;

    /**
     * 创建订单
     * @param request 订单创建请求对象，包含订单信息和菜品列表
     * @param httpServletRequest HTTP请求对象，用于获取用户JWT
     * @return 操作结果：成功返回订单信息，失败返回错误信息
     */
    @RequestMapping("/create")
    public RestBean createOrder(@RequestBody OrderCreationRequest request, HttpServletRequest httpServletRequest) {
        // 从请求中获取订单信息
        OrderInfo orderInfo = request.getOrderInfo();
        // 从请求中获取订单包含的菜品列表
        List<OrderMenuInfo> menuInfos = request.getMenuInfos();
        // 校验菜品列表是否为空
        if (menuInfos.isEmpty()) return RestBean.failure(403, "菜单不能为空");
        // 从JWT中获取用户ID
        String uuid = jwtUtil.getJwtUsername(httpServletRequest);
        // 生成唯一的订单ID
        String orderId = UUID.randomUUID().toString();
        // 设置订单ID
        orderInfo.setOrderId(orderId);
        // 设置订单用户ID
        orderInfo.setUserId(uuid);
        // 设置订单创建时间
        orderInfo.setInputTime(new Date());
        // 设置订单初始状态为"未支付"
        orderInfo.setApplyState(0);
        // 根据订单类型设置配送费（1堂食，2外卖）
        if (orderInfo.getType() == 2) {
            orderInfo.setMoney(BigDecimal.valueOf(2));
        } else {
            orderInfo.setMoney(BigDecimal.valueOf(0));
        }
        // 遍历菜品列表计算订单总金额并保存菜品关联信息
        for (OrderMenuInfo menu : menuInfos) {
            // 设置菜品关联的订单ID
            menu.setOrderId(orderId);
            // 设置菜品关联记录的创建时间
            menu.setInputTime(new Date());
            // 根据菜品ID查询菜品信息
            MenuInfo menuInfo = menuInfoService.getById(menu.getMenuId());
            // 计算单项菜品金额并累加到订单总金额
            if (menuInfo != null && menuInfo.getMenuPrice() != null) {
                BigDecimal menuPrice = new BigDecimal(menuInfo.getMenuPrice().toString());
                BigDecimal itemCost = menuPrice.multiply(BigDecimal.valueOf(menu.getCount()));
                orderInfo.setMoney(orderInfo.getMoney().add(itemCost));
            }
            // 保存订单与菜品的关联记录
            orderMenuInfoService.save(menu);
        }
        // 保存订单信息到数据库
        return orderInfoService.save(orderInfo) ? RestBean.success(orderInfo) : RestBean.failure(500, "订单创建失败");
    }

    /**
     * 查询当前用户的订单列表
     * @param request HTTP请求对象，用于获取用户JWT
     * @return 操作结果：成功返回订单视图列表，失败返回错误信息
     */
    @RequestMapping("/query")
    public RestBean queryOrder(HttpServletRequest request) {
        // 从JWT中获取用户ID
        String uuid = jwtUtil.getJwtUsername(request);
        // 查询用户的订单列表（按创建时间降序排列）
        List<OrderInfo> orderInfos = orderInfoService.list(new QueryWrapper<OrderInfo>()
                .eq("user_id", uuid).orderByDesc("input_time"));
        // 创建订单视图列表用于封装详细订单信息
        List<OrderView> orderViews = new ArrayList<>();
        // 遍历订单列表转换为订单视图对象
        for (OrderInfo order : orderInfos) {
            OrderView orderView = createOrderView(order);
            orderViews.add(orderView);
        }
        // 返回订单视图列表
        return RestBean.success(orderViews);
    }

    /**
     * 查看订单详情
     * @param id 订单ID，通过路径变量传入
     * @return 操作结果：成功返回订单视图对象，失败返回错误信息
     */
    @RequestMapping("/view/{id}")
    public RestBean viewSomeone(@PathVariable String id) {
        // 根据订单ID查询订单信息
        OrderInfo order = orderInfoService.getById(id);
        // 校验订单是否存在
        if (order == null) return RestBean.failure(403, "不存在该订单信息");
        // 将订单信息转换为订单视图对象
        OrderView orderView = createOrderView(order);
        // 返回订单视图对象
        return RestBean.success(orderView);
    }

    /**
     * 订单支付
     * @param orderId 订单ID，通过路径变量传入
     * @param request HTTP请求对象，用于获取用户JWT
     * @return 操作结果：成功返回订单信息，失败返回错误信息
     */
    @RequestMapping("/apply/{orderId}")
    public RestBean applyOrder(@PathVariable String orderId, HttpServletRequest request) {
        // 根据订单ID查询订单信息
        OrderInfo orderInfo = orderInfoService.getById(orderId);
        // 从JWT中获取用户ID
        String uuid = jwtUtil.getJwtUsername(request);
        // 根据用户ID查询用户信息
        UserInfo userInfo = userInfoService.getById(uuid);
        // 将用户余额转换为BigDecimal类型
        BigDecimal userMoney = BigDecimal.valueOf(Double.parseDouble(userInfo.getMoney()));
        // 校验用户余额是否足够
        if (userMoney.compareTo(orderInfo.getMoney()) < 0) {
            return RestBean.failure(403, "余额不足");
        }
        // 扣除用户余额
        userInfo.setMoney(userMoney.subtract(orderInfo.getMoney()).toString());
        // 更新用户信息
        userInfoService.updateById(userInfo);
        // 设置订单状态为"已支付"
        orderInfo.setApplyState(1);
        // 更新订单信息
        return orderInfoService.updateById(orderInfo) ? RestBean.success(orderInfo) : RestBean.failure(403, "支付失败");
    }

    /**
     * 查询商家的订单列表（分页）
     * @param page 当前页码，通过路径变量传入
     * @param item 每页显示数量，通过路径变量传入
     * @param request HTTP请求对象，用于获取用户JWT
     * @return 操作结果：成功返回订单列表，失败返回错误信息
     */
    @RequestMapping("/orderForShop/{page}/{item}")
    public RestBean orderForShop(@PathVariable int page, @PathVariable int item, HttpServletRequest request) {
        // 从JWT中获取用户ID（当前操作用户为商家）
        String uuid = jwtUtil.getJwtUsername(request);
        // 获取商家的店铺信息
        ShopInfo shopMasterId = shopInfoService.getOne(new QueryWrapper<ShopInfo>()
                .eq("shop_master_id", uuid)
        );
        // 校验店铺是否存在
        if (shopMasterId == null)
            return RestBean.failure(403, "店铺信息异常");
        // 调用服务层方法查询商家的订单列表（分页）
        return RestBean.success(orderInfoService.queryByShop(page, item, shopMasterId.getShopId()));
    }

    /**
     * 订单退款
     * @param orderId 订单ID，通过路径变量传入
     * @return 操作结果：成功返回订单信息，失败返回错误信息
     */
    @RequestMapping("/refund/{orderId}")
    public RestBean refundOrder(@PathVariable String orderId) {
        // 根据订单ID查询订单信息
        OrderInfo orderInfo = orderInfoService.getById(orderId);
        // 校验订单是否存在
        if (orderInfo == null) return RestBean.failure(403, "不存在该订单信息");
        // 校验订单状态是否允许退款
        if (orderInfo.getApplyState() == 0) return RestBean.failure(403, "该订单还未付款");
        if (orderInfo.getApplyState() == 2) return RestBean.failure(403, "该订单已评价，不予退款");
        // 设置订单状态为"已退款"
        orderInfo.setApplyState(-1);
        // 获取订单用户信息
        UserInfo userInfo = userInfoService.getById(orderInfo.getUserId());
        // 退还用户余额
        userInfo.setMoney(BigDecimal.valueOf(Double.parseDouble(userInfo.getMoney())).add(orderInfo.getMoney()).toString());
        // 更新订单和用户信息
        if (orderInfoService.updateById(orderInfo) && userInfoService.updateById(userInfo)) {
            return RestBean.success(orderInfo);
        }
        return RestBean.failure(500, "退款失败");
    }

    /**
     * 创建订单视图对象（封装订单详细信息）
     * @param order 订单信息实体
     * @return 订单视图对象
     */
    private OrderView createOrderView(OrderInfo order) {
        // 创建订单视图对象
        OrderView orderView = new OrderView();
        // 设置订单ID
        orderView.setOrderId(order.getOrderId());
        // 设置订单金额
        orderView.setMoney(order.getMoney());
        // 设置订单地址（若存在）
        if (userAddressService.count(new QueryWrapper<UserAddress>().eq("address_id", order.getAddressId())) != 0) {
            orderView.setAddress(userAddressService.getById(order.getAddressId()).getAddress());
        } else {
            orderView.setAddress("未知");
        }
        // 设置订单备注
        orderView.setDemo(order.getDemo());
        // 设置订单所属店铺名称
        orderView.setShopName(shopInfoService.getById(order.getShopId()).getShopName());
        // 设置订单类型
        orderView.setType(order.getType());
        // 设置订单状态
        orderView.setApplyState(order.getApplyState());
        // 设置订单创建时间
        orderView.setInputDate(order.getInputTime());
        // 查询订单包含的菜品列表
        List<OrderMenuInfo> orderMenuInfos = orderMenuInfoService.list(new QueryWrapper<OrderMenuInfo>().eq("order_id", order.getOrderId()));
        // 创建菜品计数列表
        List<MenuCount> menuCounts = new ArrayList<>();
        // 遍历菜品列表封装详细信息
        for (OrderMenuInfo orderMenuInfo : orderMenuInfos) {
            MenuCount menuCount = new MenuCount();
            menuCount.setCount(orderMenuInfo.getCount());
            MenuInfo menuInfo = menuInfoService.getById(orderMenuInfo.getMenuId());
            menuCount.setMenuPrice(menuInfo.getMenuPrice());
            menuCount.setMenuName(menuInfo.getMenuName());
            menuCount.setMenuPicture(menuInfo.getMenuPicture());
            menuCount.setMenuId(orderMenuInfo.getMenuId());
            menuCount.setCount(orderMenuInfo.getCount());
            menuCounts.add(menuCount);
        }
        // 设置订单包含的菜品列表
        orderView.setMenuCounts(menuCounts);
        // 查询订单配送信息
        OrderSendInfo orderSendInfo = orderSendInfoService.
                getOne(new QueryWrapper<OrderSendInfo>().eq("order_id", order.getOrderId()));
        // 封装订单配送状态和配送员信息（若存在）
        if (orderSendInfo != null) {
            orderView.setSendState(orderSendInfo.getState() == 0 ? "正在配送" :
                    orderSendInfo.getState() == 1 ? "已送达" :
                            orderSendInfo.getState() == -1 ? "骑手已退单，待其他骑手接单" : "未知");
            orderView.setSenderName(JSON.toJSONString(userInfoService.getById(senderInfoService.getById(orderSendInfo.getSenderId())).getUsername()));
        }
        // 返回订单视图对象
        return orderView;
    }
}